#include "network.h"

network::network() {
	this->status = NET_DISCONNECTED;
	this->sockset = SDLNet_AllocSocketSet(NET_MAX_CONNECTIONS);
	this->conn_count = 0;
}

network::~network() {
		SDLNet_FreeSocketSet(this->sockset);
}

int network::connect(const char *host, Uint16 port) {
	IPaddress ip;

	resolve(host, port, &ip);
	if ((this->conn_list[0] = SDLNet_TCP_Open(&ip)) == NULL) {
		log_config.print(PACMEN_LOG_ERROR, PACMEN_LOG_FILEATTRIBUTE, "Error calling SDLNet_TCP_Open()\n");
		return EXIT_FAILURE;
	}
	SDLNet_TCP_AddSocket(this->sockset, this->conn_list[0]);
	this->status = NET_CONNECTED;
	this->conn_count = 1;
	return EXIT_SUCCESS;
}

int network::check() {
	SDLNet_CheckSockets(this->sockset, 0);
}

/* Static methods */
int network::resolve(const char *host, Uint16 port, IPaddress *ip) {
	if (SDLNet_ResolveHost(ip, host, port) == -1)
		return EXIT_FAILURE;
	return EXIT_SUCCESS;
}

int network::send(void *buf, size_t size, TCPsocket socket, size_t *bytes) {
	if ((*bytes = SDLNet_TCP_Send(socket, buf, size)) <= 0) {
		log_config.print(PACMEN_LOG_ERROR, PACMEN_LOG_FILEATTRIBUTE, "Error on send() call\n");
		return EXIT_FAILURE;
	}
}

int network::receive(void *buf, size_t max_size, TCPsocket socket, size_t *bytes) {
	if ((*bytes = SDLNet_TCP_Recv(socket, buf, max_size)) <= 0) {
		log_config.print(PACMEN_LOG_ERROR, PACMEN_LOG_FILEATTRIBUTE, "Error on recv() call\n");
		return EXIT_FAILURE;
	}
}

int network::close(TCPsocket socket) {
	if (socket) {
		SDLNet_TCP_Close(socket);
		return EXIT_SUCCESS;
	}
	return EXIT_FAILURE;
}

int network::send(void *buf, size_t size, size_t *bytes) {
	if ((*bytes = SDLNet_TCP_Send(this->conn_list[0], buf, size)) <= 0) {
		log_config.print(PACMEN_LOG_ERROR, PACMEN_LOG_FILEATTRIBUTE, "Error calling SDLNet_TCP_Send()\n");
		this->close();
		return EXIT_FAILURE;
	}
}

int network::receive(void *buf, size_t max_size, size_t *bytes) {
	if ((*bytes = SDLNet_TCP_Recv(this->conn_list[0], buf, max_size)) <= 0) {
		log_config.print(PACMEN_LOG_ERROR, PACMEN_LOG_FILEATTRIBUTE, "Error calling SDLNet_TCP_Recv()\n");
		this->close();
		return EXIT_FAILURE;
	}
}

int network::close() {
	if (!this->conn_list[0])
		return EXIT_FAILURE;

	SDLNet_TCP_Close(this->conn_list[0]);
	SDLNet_TCP_DelSocket(this->sockset, this->conn_list[0]);
	this->conn_list[0] = NULL;
	return EXIT_SUCCESS;
}
